// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.api

import android.content.Context
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import xyz.apiote.bimba.czwek.R
import xyz.apiote.bimba.czwek.api.transitous.api.TimetableApi
import xyz.apiote.bimba.czwek.network.isNetworkAvailable
import xyz.apiote.bimba.czwek.repo.Colour
import xyz.apiote.bimba.czwek.repo.CongestionLevel
import xyz.apiote.bimba.czwek.repo.Event
import xyz.apiote.bimba.czwek.repo.LineStub
import xyz.apiote.bimba.czwek.repo.LineType
import xyz.apiote.bimba.czwek.repo.OccupancyStatus
import xyz.apiote.bimba.czwek.repo.Position
import xyz.apiote.bimba.czwek.repo.Stop
import xyz.apiote.bimba.czwek.repo.StopEvents
import xyz.apiote.bimba.czwek.repo.TrafficResponseException
import xyz.apiote.bimba.czwek.repo.Vehicle
import xyz.apiote.bimba.czwek.units.Mps
import java.math.BigDecimal
import java.time.Instant
import java.time.LocalDate
import java.time.OffsetDateTime
import java.time.ZoneId

suspend fun getTransitousDepartures(
	context: Context,
	stop: String,
	date: LocalDate?,
	limit: Int?,
	exact: Boolean
): StopEvents {
	if (!isNetworkAvailable(context)) {
		throw TrafficResponseException(0, "", Error(0, R.string.error_offline, R.drawable.error_net))
	}

	return withContext(Dispatchers.IO) {
		// TODO shouldn't it be start-of-day in stop's timezone?
		val datetime = date?.let {
			OffsetDateTime.of(date.atStartOfDay(), ZoneId.systemDefault().rules.getOffset(Instant.now()))
		}
		val times = TimetableApi().stoptimes(stop, limit ?: 12, datetime)
		var stopName = ""
		var latitude = BigDecimal(0)
		var longitude = BigDecimal(0)
		val departures = times.stopTimes.filter {
			!exact || stop == it.place.stopId
		}.mapNotNull {
			if ((it.place.departure ?: it.place.arrival) == null) {
				null
			} else {
				latitude = it.place.lat
				longitude = it.place.lon
				stopName = it.place.name
				Event(
					it.tripId + it.source,
					it.place.arrival?.let {
						Time.fromOffsetTime(it, ZoneId.systemDefault())
					},
					it.place.departure?.let {
						Time.fromOffsetTime(it, ZoneId.systemDefault())
					},
					0u,
					it.realTime,
					Vehicle(
						it.tripId,
						Position(0.0, 0.0),
						0u,
						Mps(0),
						LineStub(
							it.routeShortName,
							LineType.fromTransitous2(it.mode),
							Colour.fromHex(it.routeColor)
						),
						it.headsign,
						CongestionLevel.UNKNOWN,
						OccupancyStatus.UNKNOWN
					),
					boarding = 0xffu,
					alerts = emptyList(),
					exact = true,
					terminusArrival = it.place.departure == null
				)
			}
		}
		StopEvents(
			departures,
			Stop(
				stop,
				stopName,
				stopName,
				"",
				"transitous",
				Position(latitude.toDouble(), longitude.toDouble()),
				listOf(),
				null
			),
			listOf()
		)
	}
}
